package com.leantech.android.browser.browser.inject

import android.graphics.Point
import android.os.SystemClock
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.ViewGroup
import android.webkit.WebView
import com.leantech.android.browser.browser.getStringFromAsset
import com.leantech.android.browser.browser.web.RocketWebView
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

fun WebView.eval(js: String) {
    evaluateJavascript(js.trimIndent()) {}
}

fun WebView.eval(js: String, callback: (String) -> Unit) {
    evaluateJavascript(js.trimIndent()) {
        callback(it)
    }
}

suspend fun RocketWebView.getSelectedText() = suspendCoroutine<String> { continuation ->
    val js = "window.getSelection().toString();"
    eval(js) { value ->
        continuation.resume(value.substring(1, value.length - 1))
    }
}

fun RocketWebView.getReaderModeJs(): String {
    return getStringFromAsset(context, "MozReadability.js")
}

fun RocketWebView.webContentScrollTop() {
    eval("javascript:(function() { window.scrollTo(0, 0); })()")
}

fun RocketWebView.getReaderModeBodyText(callback: (String) -> Unit) {
    eval(
        """
            javascript:(function() {
                var documentClone = document.cloneNode(true);
                var article = new Readability(documentClone, {classesToPreserve: preservedClasses, debug: true}).parse();
                return article.textContent;
            })()
        """, callback
    )
}

fun RocketWebView.disableReaderMode() {
    eval(
        "javascript:(function() {" + "document.body.innerHTML = document.innerHTMLCache;" + "document.body.classList.remove(\"mozac-readerview-body\");" + "window.scrollTo(0, 0);" + "})()"
    )
}

fun RocketWebView.replaceWithReaderModeBody(callback: ((String) -> Unit)?) {
    val replaceWithReaderModeBodyJs = """
            var documentClone = document.cloneNode(true);
            var article = new Readability(documentClone, {classesToPreserve: preservedClasses}).parse();
            document.innerHTMLCache = document.body.innerHTML;

            article.readingTime = getReadingTime(article.length, document.lang);

            document.body.outerHTML = createHtmlBody(article)

            // change font type
            var bodyClasses = document.body.classList;
            bodyClasses.add("serif");
            document.getElementsByName('viewport')[0].setAttribute('content', 'width=device-width');
        """

    if (callback != null) {
        val getRawTextJs = " return document.getElementsByTagName('html')[0].innerText; "
        eval(
            "(function(){ ${String.format(replaceWithReaderModeBodyJs, url)} $getRawTextJs })();",
            callback
        )
    } else {
        eval("(function(){ ${String.format(replaceWithReaderModeBodyJs, url)} })();")
    }

}

/**
 * 移除所选
 */
fun RocketWebView.removeTextSelection() {
    eval(
        """
            javascript:(function() {
                     var sel = w.getSelection();
                     sel.removeAllRanges();
                 }
            )()
        """
    )
}

fun RocketWebView.selectLinkText(point: Point) {
    eval(
        """
            javascript:(function() {
                 var tt = w._touchTarget;
                 if(tt){
                     var hrefAttr = tt.getAttribute("href");
                     tt.removeAttribute("href");
                     w._hrefAttr = hrefAttr;
                     
                     var sel = w.getSelection();
                     sel.removeAllRanges();
                 }
            })()
        """
    ) {
        postDelayed({
            simulateLongClick(point)
        }, 0)
    }
}

/**
 * 模拟长按
 */
fun RocketWebView.simulateLongClick(point: Point) {
    isSelectingText = true
    val downTime = SystemClock.uptimeMillis()
    val downEvent = MotionEvent.obtain(
        downTime, downTime, KeyEvent.ACTION_DOWN, (point.x + 20).toFloat(), point.y.toFloat(), 0
    )
    (this.parent as ViewGroup).dispatchTouchEvent(downEvent)
    val upEvent = MotionEvent.obtain(
        downTime, downTime + 700, KeyEvent.ACTION_UP, point.x.toFloat(), point.y.toFloat(), 0
    )
    postDelayed(
        {
            (this.parent as ViewGroup).dispatchTouchEvent(upEvent)
            downEvent.recycle()
            upEvent.recycle()
        }, 700
    )
    postDelayed(
        {
            eval(
                """
                        var tt = w._touchTarget;
                        if(tt){
                            tt.setAttribute("href", w._hrefAttr);
                        }
                """
            )
            isSelectingText = false
        }, 1000
    )
}


/**
 * callback invoke JsWebInterface.getAnchorPosition
 */
fun RocketWebView.addSelectionChangeListener() {
    eval(
        """
            var selectedText = "";
            function getSelectionPositionInWebView() {
    let selection = window.getSelection();
    
    if (selection) {
        let range = selection.getRangeAt(0);
        let startNode = range.startContainer;
        let startOffset = range.startOffset;
        let endNode = range.endContainer;
        let endOffset = range.endOffset;
        
        let start = getRectInWebView(startNode, startOffset);
        let end = getRectInWebView(endNode, endOffset);
        
            // Send anchor position to Android
            if (selection.toString() != selectedText) {
                selectedText = selection.toString();
                if (selectedText.length > 0) {
                    androidApp.getAnchorPosition(start.left, start.top, end.right, end.bottom);
                }
            }
    }
}

function getRectInWebView(node, offset) {
    let range = document.createRange();
    range.setStart(node, offset);
    range.setEnd(node, offset);
    let rect = range.getBoundingClientRect();

    return rect;
}

// Call the function to get selection position
document.addEventListener("selectionchange", function() {
    getSelectionPositionInWebView();
    });
        """
    )
}